import {RequestOptions} from "https";
import FormData from "form-data";
import config from '../project.config.json'
import https from 'https'
import querystring, {ParsedUrlQueryInput} from 'querystring'
import {Stream} from "stream";


const baseHeaders = {
  accept: 'application/json, text/javascript, */*; q=0.01',
  'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
  'accept-language': 'zh-CN,zh;q=0.9',
  pragma: 'no-cache',
  'sec-fetch-dest': 'empty',
  'sec-fetch-mode': 'cors',
  'sec-fetch-site': 'same-origin',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36',
  referer: 'https://pc.woozooo.com/mydisk.php?item=files&action=index&u=1702063',
  'origin': 'https://pc.woozooo.com',
}
exports.baseHeaders = baseHeaders

function parseJson(str) {
  try {
    return JSON.parse(str)
  } catch (e) {
    return str
  }
}

interface RequestParams<T> extends RequestOptions {
  url: string
  body?: T
  onData?: (bytes: number) => void
}

const cookie = config.cookies[0]

function request<T = any, R extends FormData | ParsedUrlQueryInput = any>({body, onData, url, ...params}: RequestParams<R>): Promise<T> {
  return new Promise((resolve, reject) => {
    const fullUrl = url || `${config.uploadUrl}${params.path}`
    const u = new URL(fullUrl)

    const headers = {
      ...baseHeaders,
      cookie,
      ...params.headers,
    }

    const options: RequestOptions = {
      method: 'post',
      path: u.pathname,
      protocol: u.protocol,
      host: u.host,
      ...params,
    }

    let data
    if (body) {
      if (isFormData(body)) {
        Object.assign(headers, body.getHeaders())
      } else {
        data = querystring.stringify(body as any)
      }
    }

    const req = https.request({
      ...options,
      headers,
    }, res => {
      let data = ''
      res.setEncoding('utf8')
      res.on("data", chunk => {
        data += chunk
      })
      res.on("end", () => {
        const json = parseJson(data)
        resolve(json)
      })
      res.on("error", err => {
        reject(err)
      })
    })

    req.on("error", err => {
      console.log(`req error:`, err)
    })

    if (!isFormData(body)) {
      req.write(data);
      req.end();
    } else {
      if (typeof onData === "function") {
        let bytes = 0
        body.on('data', chunk => {
          bytes += chunk.length
          onData(bytes)
        })
      }

      body.pipe(req);
    }
  })
}

export = request

function isFormData(body): body is FormData {
  return body instanceof Stream
}
